package cn.getech.data.development.service.impl;

import avro.shaded.com.google.common.collect.Lists;
import cn.getech.data.development.constant.*;
import cn.getech.data.development.entity.*;
import cn.getech.data.development.entity.AllPermissionConfig;
import cn.getech.data.development.entity.TableFieldInfo;
import cn.getech.data.development.entity.TableInfo;
import cn.getech.data.development.entity.TableRegisterEntity;
import cn.getech.data.development.entity.dataMap.DataApplication;
import cn.getech.data.development.entity.*;
import cn.getech.data.development.entity.flink.BdpRealTableField;
import cn.getech.data.development.entity.flink.BdpRealTableInfo;
import cn.getech.data.development.entity.permission.*;
import cn.getech.data.development.mapper.*;
import cn.getech.data.development.mapper.TableRelationMapper;
import cn.getech.data.development.mapper.dataMap.DataApplicationMapper;
import cn.getech.data.development.mapper.*;
import cn.getech.data.development.mapper.flink.BdpRealTableFieldMapper;
import cn.getech.data.development.mapper.flink.BdpRealTableInfoMapper;
import cn.getech.data.development.mapper.permission.SysRoleDataPermissionMapper;
import cn.getech.data.development.mapper.permission.SysTenantDataPermissionMapper;
import cn.getech.data.development.model.req.search.DataSearchReq;
import cn.getech.data.development.model.vo.BdpRealTableInfoVO;
import cn.getech.data.development.service.*;
import cn.getech.data.development.utils.DataPermissionUtil;
import cn.getech.data.development.vo.SecurityLevelVO;
import cn.getech.data.intelligence.common.exception.RRException;
import cn.getech.data.intelligence.common.utils.PageUtils;
import cn.getech.data.intelligence.common.utils.Query;
import cn.getech.system.center.entity.SysSecurityDataLevelEntity;
import cn.getech.system.center.entity.SysTenantUser;
import cn.getech.system.center.service.SysSecurityDataLevelService;
import cn.getech.system.center.service.SysTenantUserService;
import cn.getech.system.center.utils.ShiroUtils;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

@Service
public class BdpRealTableInfoServiceImpl extends ServiceImpl<BdpRealTableInfoMapper,
        BdpRealTableInfo> implements BdpRealTableInfoService {

    @Autowired
    private BdpRealTableFieldMapper bdpRealTableFieldMapper;
    @Autowired
    private SysRoleDataPermissionMapper sysRoleDataPermissionMapper;

    @Autowired
    private SysTenantDataPermissionMapper sysTenantDataPermissionMapper;
    @Autowired
    private TableRelationMapper tableInfoRelationMapper;
    @Autowired
    private DataPermissionService dataPermissionService;

    @Autowired
    private DataApplicationMapper dataApplicationMapper;

    @Autowired
    private RangerDataService rangerDataService;
    @Autowired
    private SysSecurityDataLevelService sysSecurityDataLevelService;
    @Autowired
    private TableRegisterService tableRegisterService;

    @Autowired
    private SysTenantUserService sysTenantUserService;
    @Autowired
    private IAllPermissionConfigService iAllPermissionConfigService;

    @Override
    public List<Map<String, Object>> getUserList(Integer type, Integer procId) {
        return tableInfoRelationMapper.getUserList(type, procId);
    }

    /**
     * 根据角色id 和表数据 查询和生成权限信息
     *
     * @param roleId  角色id
     * @param records 表信息
     */
    private List<RealTablePermission> getDataList(Long roleId, List<BdpRealTableInfo> records) {
        // 查询数据权限信息
        Map<String, SysRoleDataPermission> permissionMap = Maps.newHashMap();
        if (roleId != null) {
            List<Integer> dataTypeList = new ArrayList<>(2);
            dataTypeList.add(PermissionTypeEnum.REAL_TABLE.getType());
            dataTypeList.add(PermissionTypeEnum.REAL_TABLE_FILED.getType());
            SysRoleDataPermissionExample param = new SysRoleDataPermissionExample();
            param.createCriteria().andRoleIdEqualTo(roleId).andDataTypeIn(dataTypeList);
            List<SysRoleDataPermission> list = sysRoleDataPermissionMapper.selectByExample(param);
            if (CollectionUtils.isNotEmpty(list)) {
                for (SysRoleDataPermission sysRoleDataPermission : list) {
                    permissionMap.put(sysRoleDataPermission.getDataId()
                                    + "-" + sysRoleDataPermission.getDataType(),
                            sysRoleDataPermission);
                }
            }
        }
        List<RealTablePermission> dataList = new ArrayList<>();
        //查询字段信息
        Set<Integer> tableIds = Sets.newHashSet();
        for (BdpRealTableInfo record : records) {
            tableIds.add(record.getId());
        }
        Long userId = ShiroUtils.getUserId();
        List<BdpRealTableField> fieldList = bdpRealTableFieldMapper.selectListByTableIds(tableIds);
        if (!DataPermissionUtil.isAdmin(userId.intValue())) {
            //按照权限过滤字段
            List<Integer> ids = DataPermissionUtil.getDataIds(userId.intValue(),
                    PermissionTypeEnum.REAL_TABLE_FILED.getType(), PermissionTypeEnum.ASSIGN.getType());
            fieldList = fieldList.stream().filter(
                    s -> ids.contains(s.getId()) || userId.equals(s.getCreateUser())
            ).collect(Collectors.toList());
        }
        Map<Integer, List<BdpRealTableField>> groupByMaps = fieldList.stream().collect(Collectors.groupingBy(BdpRealTableField::getTableId));
        for (BdpRealTableInfo record : records) {
            List<BdpRealTableField> tableFieldList = groupByMaps.get(record.getId());
            List<RealTableFieldInfoPermission> tableFieldPerList = new ArrayList<>();
            if (CollectionUtils.isNotEmpty(tableFieldList)) {
                for (BdpRealTableField tableFieldInfo : tableFieldList) {
                    SysRoleDataPermission permission = permissionMap.get(tableFieldInfo.getId() + "-"
                            + PermissionTypeEnum.REAL_TABLE_FILED.getType());
                    if (permission != null) {
                        RealTableFieldInfoPermission tp = new RealTableFieldInfoPermission(tableFieldInfo, permission);
                        tableFieldPerList.add(tp);
                    } else {
                        RealTableFieldInfoPermission tp = new RealTableFieldInfoPermission(tableFieldInfo, null);
                        tp.defaultValue(roleId, tableFieldInfo.getId(), PermissionTypeEnum.REAL_TABLE_FILED.getType());
                        tableFieldPerList.add(tp);
                    }
                }
            }
            SysRoleDataPermission permission = permissionMap.get(record.getId() + "-"
                    + PermissionTypeEnum.REAL_TABLE.getType());
            if (permission != null) {
                RealTablePermission table = new RealTablePermission(record, permission);
                table.setTableFieldInfos(tableFieldPerList);
                dataList.add(table);
            } else {
                RealTablePermission table = new RealTablePermission(record, null);
                table.setTableFieldInfos(tableFieldPerList);
                table.defaultValue(roleId, record.getId(), PermissionTypeEnum.REAL_TABLE.getType());
                dataList.add(table);
            }
        }
        return dataList;
    }

    /**
     * 根据租户id 和表数据 查询和生成权限信息
     *
     * @param tenantId 租户id
     * @param records  表信息
     */
    private List<TenantRealTablePermission> getTenantDataList(Integer tenantId, List<BdpRealTableInfo> records) {
        // 查询数据权限信息
        Map<String, SysTenantDataPermission> permissionMap = Maps.newHashMap();
        if (tenantId != null) {
            List<Integer> dataTypeList = new ArrayList<>(2);
            dataTypeList.add(PermissionTypeEnum.REAL_TABLE.getType());
            dataTypeList.add(PermissionTypeEnum.REAL_TABLE_FILED.getType());
            SysTenantDataPermissionExample param = new SysTenantDataPermissionExample();
            param.createCriteria().andTenantIdEqualTo(tenantId).andDataTypeIn(dataTypeList);
            List<SysTenantDataPermission> list = sysTenantDataPermissionMapper.selectByExample(param);
            if (CollectionUtils.isNotEmpty(list)) {
                for (SysTenantDataPermission sysTenantDataPermission : list) {
                    permissionMap.put(sysTenantDataPermission.getDataId()
                                    + "-" + sysTenantDataPermission.getDataType(),
                            sysTenantDataPermission);
                }
            }
        }
        List<TenantRealTablePermission> dataList = new ArrayList<>();
        //查询字段信息
        Set<Integer> tableIds = Sets.newHashSet();
        for (BdpRealTableInfo record : records) {
            tableIds.add(record.getId());
        }
        Long userId = ShiroUtils.getUserId();
        List<BdpRealTableField> fieldList = bdpRealTableFieldMapper.selectListByTableIds(tableIds);
        if (!DataPermissionUtil.isAdmin(userId.intValue())) {
            //按照权限过滤字段
            List<Integer> ids = DataPermissionUtil.getDataIds(userId.intValue(),
                    PermissionTypeEnum.REAL_TABLE_FILED.getType(), PermissionTypeEnum.ASSIGN.getType());
            fieldList = fieldList.stream().filter(
                    s -> ids.contains(s.getId()) || userId.equals(s.getCreateUser())
            ).collect(Collectors.toList());
        }
        Map<Integer, List<BdpRealTableField>> groupByMaps = fieldList.stream().collect(Collectors.groupingBy(BdpRealTableField::getTableId));
        for (BdpRealTableInfo record : records) {
            List<BdpRealTableField> tableFieldList = groupByMaps.get(record.getId());
            List<TenantRealTableFieldInfoPermission> tableFieldPerList = new ArrayList<>();
            if (CollectionUtils.isNotEmpty(tableFieldList)) {
                for (BdpRealTableField tableFieldInfo : tableFieldList) {
                    SysTenantDataPermission permission = permissionMap.get(tableFieldInfo.getId() + "-"
                            + PermissionTypeEnum.REAL_TABLE_FILED.getType());
                    if (permission != null) {
                        TenantRealTableFieldInfoPermission tp = new TenantRealTableFieldInfoPermission(tableFieldInfo, permission);
                        tableFieldPerList.add(tp);
                    } else {
                        TenantRealTableFieldInfoPermission tp = new TenantRealTableFieldInfoPermission(tableFieldInfo, null);
                        tp.defaultValue(tenantId, tableFieldInfo.getId(), PermissionTypeEnum.REAL_TABLE_FILED.getType());
                        tableFieldPerList.add(tp);
                    }
                }
            }
            SysTenantDataPermission permission = permissionMap.get(record.getId() + "-"
                    + PermissionTypeEnum.REAL_TABLE.getType());
            if (permission != null) {
                TenantRealTablePermission table = new TenantRealTablePermission(record, permission);
                table.setTableFieldInfos(tableFieldPerList);
                dataList.add(table);
            } else {
                TenantRealTablePermission table = new TenantRealTablePermission(record, null);
                table.setTableFieldInfos(tableFieldPerList);
                table.defaultValue(tenantId, record.getId(), PermissionTypeEnum.REAL_TABLE.getType());
                dataList.add(table);
            }
        }
        return dataList;
    }

    @Override
    public PageUtils<RealTablePermission> listPageByRole(Map<String, Object> params) {
        Long userId = ShiroUtils.getUserId();
        if (params.get("role_id") == null ||StrUtil.isBlank(params.get("role_id").toString())|| Long.valueOf(params.get("role_id").toString()) < 1) {
            return new PageUtils<>(new ArrayList<>(),0,10,1);
        }
        List<Integer> ids = DataPermissionUtil.getDataIds(PermissionTypeEnum.REAL_TABLE.getType(),
                PermissionTypeEnum.ASSIGN.getType());
        if (CollectionUtils.isEmpty(ids)) {
            ids.add(-1);//无权限
        }
        if(params.get("userId")!=null){
            params.put("createUser",params.get("userId"));
        }
        params.put("ids", ids);
        params.put("tableType", RealTableType.INNER.getCode());
        params.put("tenantId", ShiroUtils.getTenantId());
        params.put("userId", ShiroUtils.getUserId().intValue());
        if(params.get("cateGoryId")!=null){
            String cateGoryId = (String) params.get("cateGoryId");
            if(StrUtil.isNotBlank(cateGoryId)){
                List<Integer> list = this.baseMapper.selectTableIds(Integer.valueOf(cateGoryId));
                if(list.size()==0){
                    list.add(-1);
                }
                List<Integer> intersection = ids.stream().filter(item -> list.contains(item)).collect(Collectors.toList());
                if(intersection.size()==0){
                    intersection.add(-1);
                }
                params.put("ids", intersection);
            }
        }
        IPage<BdpRealTableInfo> dataPage = new Query<BdpRealTableInfo>().getPage(params);
        IPage<BdpRealTableInfo> page = baseMapper.listPageByRole(dataPage, params);
        List<RealTablePermission> dataList = new ArrayList<>();
        Long roleId = 0L;
        if (params.get("role_id") != null) {
            roleId = Long.parseLong(params.get("role_id").toString());
        }
        List<BdpRealTableInfo> records = page.getRecords();
        if (CollectionUtils.isNotEmpty(records)) {
            dataList = getDataList(roleId, records);
        }
        return new PageUtils<>(dataList, page.getTotal(),
                (int) page.getSize(), (int) page.getCurrent());
    }

    @Override
    public PageUtils<TenantRealTablePermission> listPageByTenant(Map<String, Object> params) {
        Long userId = ShiroUtils.getUserId();
        if (!DataPermissionUtil.isAdmin(userId.intValue())) {
            params.put("createUser", userId);
        }
        params.put("tableType", RealTableType.INNER.getCode());
        params.put("userId", userId);
        params.put("currentTenantId", ShiroUtils.getTenantId());
        IPage<BdpRealTableInfo> dataPage = new Query<BdpRealTableInfo>().getPage(params);
        IPage<BdpRealTableInfo> page = baseMapper.listPageByTenant(dataPage, params);
        List<TenantRealTablePermission> dataList = new ArrayList<>();
        Integer tenantId = 0;
        if (params.get("tenant_id") != null) {
            tenantId = Integer.parseInt(params.get("tenant_id").toString());
        }
        List<BdpRealTableInfo> records = page.getRecords();
        if (CollectionUtils.isNotEmpty(records)) {
            dataList = getTenantDataList(tenantId, records);
        }
        return new PageUtils<>(dataList, page.getTotal(),
                (int) page.getSize(), (int) page.getCurrent());
    }

    @Override
    public String checkPermission(BdpRealTableInfoVO param) {
        Long userId = ShiroUtils.getUserId();
        BdpRealTableInfoVO tableInfo = queryDetail(param.getId());
        if (!userId.equals(tableInfo.getCreateUser())
                && RealTableType.INNER.getCode().equals(tableInfo.getTableType())
        ) {  //不是自己创建的数据 才做权限校验
            if (!dataPermissionService.checkDataPermission(tableInfo.getId(),
                    PermissionTypeEnum.REAL_TABLE.getType(), PermissionTypeEnum.UPDATE.getType())) {
                return DataDevelopmentBizExceptionEnum.UPDATE_NO_PERMISSION.getMessage();
            }
            if (tableInfo.getId() != null) {
                if (param.getFieldList() != null) {//存在新增字段
                    List<BdpRealTableField> filedNew = param.getFieldList()
                            .stream().filter(s -> s.getId() == null).collect(Collectors.toList());
                    if (CollectionUtil.isNotEmpty(filedNew)) {
                        if (!dataPermissionService.checkDataPermission(tableInfo.getId(),
                                PermissionTypeEnum.REAL_TABLE.getType(), PermissionTypeEnum.CREATE.getType())) {
                            return DataDevelopmentBizExceptionEnum.FIELD_CREATE_NO_PERMISSION.getMessage();
                        }
                    }
                    //先查询出原来的字段
                    List<BdpRealTableField> oldFieldInfos = tableInfo.getFieldList();
                    List<Integer> oldIds = oldFieldInfos.stream().map(BdpRealTableField::getId).collect(Collectors.toList());
                    //现有的字段,不是新增的字段,需要编辑的字段
                    Set<Integer> updateIds = param.getFieldList().stream().filter(s -> s.getId() != null)
                            .map(BdpRealTableField::getId).collect(Collectors.toSet());
                    List<Integer> needUpdateTableFieldIds = new ArrayList<>(updateIds);
                    List<Integer> needDelTableFieldIds = new ArrayList<>();
                    for (Integer oldId : oldIds) {
                        if (!updateIds.contains(oldId)) {
                            needDelTableFieldIds.add(oldId);
                        }
                    }
                    List<BdpRealTableField> ownFieldInfos = Lists.newArrayList();//自己的创建的字段
                    ownFieldInfos.addAll(oldFieldInfos.stream().filter(s -> userId.equals(s.getCreateUser()))
                            .collect(Collectors.toList()));
                    ownFieldInfos.addAll(param.getFieldList().stream().filter(s -> userId.equals(s.getCreateUser()))
                            .collect(Collectors.toList()));
                    Set<Integer> ownIds = ownFieldInfos.stream().filter(s -> s.getId() != null)//自己的创建的字段id
                            .map(BdpRealTableField::getId).collect(Collectors.toSet());

                    if (!dataPermissionService.checkApplyRealPermission(tableInfo.getId(), PermissionTypeEnum.UPDATE.getType())) {
                        // 除去自己创建的字段
                        needUpdateTableFieldIds = needUpdateTableFieldIds.stream().filter(s -> !ownIds.contains(s))
                                .collect(Collectors.toList());
                        if (CollectionUtils.isNotEmpty(needUpdateTableFieldIds)) {
                            if (!dataPermissionService.checkDataPermission(needUpdateTableFieldIds,
                                    PermissionTypeEnum.REAL_TABLE_FILED.getType(), PermissionTypeEnum.UPDATE.getType())) {
                                return DataDevelopmentBizExceptionEnum.UPDATE_FIELD_NO_PERMISSION.getMessage();
                            }
                        }
                    }
                    if (!dataPermissionService.checkApplyRealPermission(tableInfo.getId(), PermissionTypeEnum.DELETE.getType())) {
                        // 除去自己创建的字段
                        needDelTableFieldIds = needDelTableFieldIds.stream().filter(s -> !ownIds.contains(s))
                                .collect(Collectors.toList());
                        if (CollectionUtils.isNotEmpty(needDelTableFieldIds)) {
                            if (!dataPermissionService.checkDataPermission(needDelTableFieldIds,
                                    PermissionTypeEnum.REAL_TABLE_FILED.getType(), PermissionTypeEnum.DELETE.getType())) {
                                return DataDevelopmentBizExceptionEnum.DELETE_FIELD_NO_PERMISSION.getMessage();
                            }
                        }
                    }

                }
            }
        }
        return null;
    }

    @Override
    public Integer checkProjectRelation(Integer id) {
        return baseMapper.checkProjectRelation(id);
    }

    @Override
    public void savePermission(List<RealTablePermission> dataList) {
        if (CollectionUtils.isNotEmpty(dataList)) {
            List<SysRoleDataPermission> permissionList = new ArrayList<>(dataList.size());
            for (RealTablePermission tableInfoPermission : dataList) {
                SysRoleDataPermission permission = tableInfoPermission.toPermission(tableInfoPermission);
                permissionList.add(permission);
                if (CollectionUtils.isNotEmpty(tableInfoPermission.getTableFieldInfos())) {
                    for (RealTableFieldInfoPermission tableFieldInfo : tableInfoPermission.getTableFieldInfos()) {
                        SysRoleDataPermission fieldPermission = tableFieldInfo.toPermission(tableFieldInfo);
                        permissionList.add(fieldPermission);
                    }
                }
            }
            dataPermissionService.savePermission(permissionList);
        }
    }

    @Override
    public void saveTenantPermission(List<TenantRealTablePermission> dataList) {
        if (CollectionUtils.isNotEmpty(dataList)) {
            List<SysTenantDataPermission> permissionList = new ArrayList<>(dataList.size());
            for (TenantRealTablePermission tableInfoPermission : dataList) {
                SysTenantDataPermission permission = tableInfoPermission.toPermission(tableInfoPermission);
                permissionList.add(permission);
                if (CollectionUtils.isNotEmpty(tableInfoPermission.getTableFieldInfos())) {
                    for (TenantRealTableFieldInfoPermission tableFieldInfo : tableInfoPermission.getTableFieldInfos()) {
                        SysTenantDataPermission fieldPermission = tableFieldInfo.toPermission(tableFieldInfo);
                        permissionList.add(fieldPermission);
                    }
                }
            }
            dataPermissionService.saveTenantPermission(permissionList);
        }
    }


    @Override
    public PageUtils<BdpRealTableInfo> queryPage(DataSearchReq params) {
        Long userId = ShiroUtils.getUserId();
        Integer tenantId = ShiroUtils.getTenantId();
        params.setTenantId(tenantId);
        if (StringUtils.isNotEmpty(params.getTopicName())) {
            String s = params.getTopicName().replace("_", "\\_");
            params.setTopicName(s);
        }
        if (StringUtils.isNotEmpty(params.getTableName())) {
            String s = params.getTableName().replace("_", "\\_");
            params.setTableName(s);
        }
        if (params.getProjectId() == null) {//项目存在  按项目查 不走权限查询
            List<Integer> resourceIds = DataPermissionUtil.getDataIds(PermissionTypeEnum.RESOURCE.getType(),
                    PermissionTypeEnum.QUERY.getType());
            if (CollectionUtils.isEmpty(resourceIds)) {
                resourceIds.add(-1);//无权限
            }
            params.setResourceIds(resourceIds);
            List<Integer> ids = DataPermissionUtil.getDataIds(PermissionTypeEnum.REAL_TABLE.getType(),
                    PermissionTypeEnum.QUERY.getType());
            if (CollectionUtils.isEmpty(ids)) {
                ids.add(-1);//无权限
            }
            params.setIds(ids);
        }
        params.setUserId(userId);
        IPage<BdpRealTableInfo> dataPage = new Page<>(params.getPage(), params.getLimit());
        IPage<BdpRealTableInfo> page = baseMapper.selectListPage(dataPage, params);
        return new PageUtils<>(page);
    }

    @Override
    public BdpRealTableInfoVO queryDetail(Integer id) {
        BdpRealTableInfo table = baseMapper.selectById(id);
        BdpRealTableInfoVO vo = new BdpRealTableInfoVO(table);
        List<BdpRealTableField> fieldList = bdpRealTableFieldMapper.selectList(new QueryWrapper<BdpRealTableField>().eq("table_id", id));
        Long userId = ShiroUtils.getUserId();
        if (!userId.equals(table.getCreateUser()) && //非创建人
                !DataPermissionUtil.isAdmin(userId.intValue()) //非管理员
                && RealTableType.INNER.getCode().equals(table.getTableType())) { //内部表
            List<Integer> tableIds = DataPermissionUtil.getApplyRealTableDataIds(userId,
                    PermissionTypeEnum.QUERY.getType());
            if (!tableIds.contains(id)) {// 申请有查询权限 则字段都有查询权限

                // 获取角色赋予的权限
                List<Integer> ids = DataPermissionUtil.getDataIds(PermissionTypeEnum.REAL_TABLE_FILED.getType(),
                        PermissionTypeEnum.QUERY.getType());
                //  获取 申请的字段权限id
                ids.addAll(DataPermissionUtil.getCreateFiledIds(id, userId, StoreTableType.ONLINE.getCode()));
                if (CollectionUtils.isEmpty(ids)) {
                    ids.add(-1);//无权限
                }
                fieldList = fieldList.stream().filter(s -> ids.contains(s.getId())
                        || userId.equals(s.getCreateUser())).collect(Collectors.toList());
            }
        }
        vo.setFieldList(fieldList);

//        Set<Integer> subjectIds = tableInfoRelationMapper.selectSubjectIds(id, StoreTableType.ONLINE.getCode());
//        if (CollectionUtils.isNotEmpty(subjectIds)) {
//            vo.setSubjectIds(subjectIds);
//        } else {
//            vo.setSubjectIds(Sets.newHashSet());
//        }
//        Set<Integer> categoryIds = tableInfoRelationMapper.selectCategoryIds(id, StoreTableType.ONLINE.getCode());
//        if (CollectionUtils.isNotEmpty(categoryIds)) {
//            vo.setCategoryIds(categoryIds);
//        } else {
//            vo.setCategoryIds(Sets.newHashSet());
//        }
        //填充表的目录id,旧有的表废弃
        List<String> categoryIdsList = tableInfoRelationMapper.selectCategoryIdsList(id);
        vo.setCateGoryIdsList(categoryIdsList);
        return vo;
    }

    public void initDataPermission(Integer tableId, Long roleId, Long userId) {
        List<RealTablePermission> dataList = Lists.newArrayList();
        RealTablePermission tp = new RealTablePermission();
        BdpRealTableInfo table = getById(tableId);
        if (userId.equals(table.getCreateUser())) {
            tp.yesValue(roleId, tableId, PermissionTypeEnum.REAL_TABLE.getType());
        } else {
            SysRoleDataPermissionExample param = new SysRoleDataPermissionExample();
            param.createCriteria().andDataTypeEqualTo(PermissionTypeEnum.REAL_TABLE.getType())
                    .andRoleIdEqualTo(roleId)
                    .andDataIdEqualTo(Long.valueOf(tableId))
                    .andQueryEqualTo(YesOrNoEnum.YES.getValue());
            List<SysRoleDataPermission> list = sysRoleDataPermissionMapper.selectByExample(param);
            if (CollectionUtils.isNotEmpty(list)) {
                tp = new RealTablePermission(table, list.get(0));
            } else {
                tp.defaultValue(roleId, tableId, PermissionTypeEnum.REAL_TABLE.getType());
            }
        }
        tp.setEnName(table.getTableName());
        List<BdpRealTableField> fieldList = bdpRealTableFieldMapper.selectList(new QueryWrapper<BdpRealTableField>().eq("table_id", tableId));
        if (CollectionUtils.isNotEmpty(fieldList)) {
            //查询自己的创建的字段信息
            List<BdpRealTableField> fieldListOwn = fieldList.stream()
                    .filter(s -> userId.equals(s.getCreateUser())).collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(fieldListOwn)) {
                ArrayList<RealTableFieldInfoPermission> fieldPerList = Lists.newArrayList();
                for (BdpRealTableField tableFieldInfo : fieldListOwn) {
                    RealTableFieldInfoPermission field = new RealTableFieldInfoPermission();
                    field.yesValue(roleId, tableFieldInfo.getId(), PermissionTypeEnum.REAL_TABLE_FILED.getType());
                    field.setEnName(tableFieldInfo.getFieldName());
                    field.setChName(tableFieldInfo.getFieldName());
                    fieldPerList.add(field);
                }
                tp.setTableFieldInfos(fieldPerList);
                dataList.add(tp);
                savePermission(dataList);
            }
        }
    }

    @Override
    public int save(BdpRealTableInfoVO param) {
        BdpRealTableInfo record = param.toDto();
        Long userId = ShiroUtils.getUserId();
        Integer tenantId = ShiroUtils.getTenantId();
        Date now = new Date();
        record.setUpdateTime(now);
        record.setUpdateUser(userId);
        TableRegisterEntity registerEntity = new TableRegisterEntity();
        if (record.getId() == null) {
            record.setTenantId(tenantId);
            List<BdpRealTableInfo> tableList = baseMapper.selectList(new QueryWrapper<BdpRealTableInfo>()
                    .eq("table_name", param.getTableName())
                    .eq("db_name", param.getDbName())
                    .eq("table_type", param.getTableType()));
            if (tableList.size() > 0) {
                return -1;//表示表已存在
            }
            tableList = baseMapper.selectList(new QueryWrapper<BdpRealTableInfo>()
                    .eq("topic_name", param.getTopicName())
                    .eq("db_name", param.getDbName())
                    .eq("table_type", param.getTableType()));
            if (tableList.size() > 0) {
                return -2;//表示topic已存在
            }
            record.setCreateTime(now);
            record.setCreateUser(userId);
            registerEntity.setRegisterType(TableRegisterTypeEnum.ONLINE_ADD.getCode());
        } else {
            registerEntity.setRegisterType(TableRegisterTypeEnum.ONLINE_UPDATE.getCode());
        }
        Integer tableType = record.getTableType();
        //新增实时内部表时,设置默认安全级别
        SecurityLevelVO securityLevelVO = getDefaultSecurityDataLevel();
        if (record.getId() == null && tableType != null && tableType == 1) {
            //新增实时内部表时,设置新增表默认安全级别
            // securityLevelVO= getDefaultSecurityDataLevel();
            record.setResourceId(YesOrNoEnum.NO.getValue());//内部表sourceId默认为0
            if (securityLevelVO != null) {
                record.setTableLevelId(securityLevelVO.getTableLevelId());
                record.setSecurityDataLevel(securityLevelVO.getSecurityDataLevelName());
            }
        }
        baseMapper.insertOrUpdateSelective(record);
        if (param.getFieldList() != null) {
            List<BdpRealTableField> addFieldList = Lists.newArrayList();
            List<BdpRealTableField> updateFieldList = Lists.newArrayList();
            for (BdpRealTableField bdpRealTableField : param.getFieldList()) {
                bdpRealTableField.setUpdateUser(userId);
                bdpRealTableField.setUpdateTime(now);
                bdpRealTableField.setDeleteFlag(YesOrNoEnum.NO.getValue());
                if (bdpRealTableField.getId() != null && param.getId() != null) { //编辑表
                    updateFieldList.add(bdpRealTableField);
                    if (bdpRealTableField.getSecurityDataLevel() == null && securityLevelVO != null) {
                        bdpRealTableField.setColcumLevelId(securityLevelVO.getColumnLevelId());
                        bdpRealTableField.setSecurityDataLevel(securityLevelVO.getSecurityDataLevelName());
                    }
                } else {
                    //新增实时内部表时,设置新增字段默认安全级别
                    if (tableType != null && tableType == 1 && securityLevelVO != null) {
                        bdpRealTableField.setColcumLevelId(securityLevelVO.getColumnLevelId());
                        bdpRealTableField.setSecurityDataLevel(securityLevelVO.getSecurityDataLevelName());
                    }
                    bdpRealTableField.setTableId(record.getId());
                    bdpRealTableField.setCreateUser(userId);
                    bdpRealTableField.setCreateTime(now);
                    bdpRealTableField.setTenantId(tenantId);
                    addFieldList.add(bdpRealTableField);
                }
            }
            //在修改字段前查询出旧字段
            List<BdpRealTableField> oldList = bdpRealTableFieldMapper.selectList(
                    new QueryWrapper<BdpRealTableField>().eq("table_id", record.getId()));
            if (CollectionUtils.isNotEmpty(updateFieldList)) {
                bdpRealTableFieldMapper.updateBatch(updateFieldList);
                Set<Integer> newIds = updateFieldList.stream().map(BdpRealTableField::getId).collect(Collectors.toSet());
                Set<Integer> deleteIds = oldList.stream().filter(s -> !newIds.contains(s.getId()))
                        .map(BdpRealTableField::getId).collect(Collectors.toSet());
                if (CollectionUtils.isNotEmpty(deleteIds)) {
                    bdpRealTableFieldMapper.delete(
                            new QueryWrapper<BdpRealTableField>().in("id", deleteIds));
                }
            } else {
                bdpRealTableFieldMapper.delete(
                        new QueryWrapper<BdpRealTableField>().eq("table_id", record.getId()));
            }
            if (CollectionUtils.isNotEmpty(addFieldList)) {
                bdpRealTableFieldMapper.batchInsert(addFieldList);
            }
        }
        if (CollectionUtils.isNotEmpty(param.getSubjectIds())
                && record.getId() != null) {
            tableInfoRelationMapper.deleteSubjectRelation(record.getId(), null, StoreTableType.ONLINE.getCode());
            for (Integer subjectId : param.getSubjectIds()) {
                tableInfoRelationMapper.addSubjectRelation(record.getId(), subjectId, userId, StoreTableType.ONLINE.getCode());
            }
        }
        if (CollectionUtils.isNotEmpty(param.getCategoryIds())
                && record.getId() != null) {
            tableInfoRelationMapper.deleteCategoryRelation(record.getId(), null, StoreTableType.ONLINE.getCode());
            for (Integer categoryId : param.getCategoryIds()) {
                tableInfoRelationMapper.addCategoryRelation(record.getId(), categoryId, userId, StoreTableType.ONLINE.getCode());
            }
        }
        if (param.getRoleId() != null && userId != null
                && RealTableType.INNER.getCode().equals(param.getTableType())) {
            initDataPermission(record.getId(), param.getRoleId(), userId);
        }

        Date curr = new Date();
        registerEntity.setTableInfoId(record.getId());
        registerEntity.setBatchNum(curr.getTime());
        long cost = curr.getTime() - now.getTime();
        registerEntity.setCost(cost);
        registerEntity.setRunTime(curr);
        registerEntity.setRunUser(userId);
        tableRegisterService.save(registerEntity);
        if(record.getId()!=null){
            if(param.getCateGoryIdsList()!=null){
                //先删除旧有关系
                this.baseMapper.deleteCategory(record.getId());
                //离线表旧有目录关系不插入，换用新的插入方式
                for(String categoryId:param.getCateGoryIdsList()){
                    Map<String,Object> map = new HashMap<>();
                    map.put("categoryId",Integer.valueOf(categoryId));
                    map.put("tableId",record.getId());
                    map.put("tenantId",ShiroUtils.getTenantId());
                    map.put("userId",ShiroUtils.getUserId().intValue());
                    map.put("datetime",new Date());
                    this.baseMapper.insertRelation(map);
                }
            }
        }
        return 0;
    }


    /**
     * @Description 获取全局默认数据安全级别名称
     * @Author chengweiping
     * @Date 2021/1/27 17:39
     */
    @Override
    public SecurityLevelVO getDefaultSecurityDataLevel() {
        SecurityLevelVO securityLevelVO = new SecurityLevelVO();
        String defaultSecurityDataLevel = null;
        try {
            SysSecurityDataLevelEntity sysSecurityDataLevelEntity = sysSecurityDataLevelService.getDefaultTableService();
            if (sysSecurityDataLevelEntity != null) {
                defaultSecurityDataLevel = sysSecurityDataLevelEntity.getName();
                securityLevelVO.setSecurityDataLevelName(defaultSecurityDataLevel);
            }
            List<AllPermissionConfig> allPermisssionList = iAllPermissionConfigService.list();
            Integer tableLevel = null, filedLevel = null;
            if (CollectionUtil.isNotEmpty(allPermisssionList)) {
                List<AllPermissionConfig> tableList = allPermisssionList.stream().filter(allPermissionConfig -> Objects.equals(PressionParamType.TABLE.getId(), allPermissionConfig.getPermissType())).collect(Collectors.toList());
                if (CollectionUtil.isNotEmpty(tableList)) {
                    tableLevel = tableList.get(0).getDataPermissionId();
                    securityLevelVO.setTableLevelId(tableLevel);
                }
                List<AllPermissionConfig> culonmList = allPermisssionList.stream().filter(allPermissionConfig -> Objects.equals(PressionParamType.CULONM.getId(), allPermissionConfig.getPermissType())).collect(Collectors.toList());
                if (CollectionUtil.isNotEmpty(tableList)) {
                    filedLevel = culonmList.get(0).getDataPermissionId();
                    securityLevelVO.setColumnLevelId(filedLevel);
                }

            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        return securityLevelVO;
    }

    /**
     * 初始化表表权限  当前登录用户创建的表和字段 默认初始化当前登录用户的第一个角色的权限
     */
    @Override
    public void initDataPermission(Integer tableId, Long roleId, Integer userId) {
        List<RealTablePermission> dataList = Lists.newArrayList();
        if (null == userId) {
            userId = ShiroUtils.getUserId().intValue();
        }
        List<Long> roleIds = new ArrayList<>();
        Set<Integer> tableIds=new HashSet<>();
        tableIds.add(tableId);
        BdpRealTableInfo table=this.getById(tableId);

        List<BdpRealTableField> fields = bdpRealTableFieldMapper.selectListByTableIds(tableIds);
        if (table == null) {
            return;
        }
        if (roleId != null) {
            roleIds.add(roleId);//给角色初始化权限
        }
        if (CollectionUtil.isNotEmpty(roleIds)) {
            RealTablePermission tp = new RealTablePermission();
            roleId = roleIds.get(0);
            if (userId.equals(table.getCreateUser().intValue())) {
                tp.yesValue(roleId, tableId, PermissionTypeEnum.REAL_TABLE.getType());
            } else {
                SysRoleDataPermissionExample param = new SysRoleDataPermissionExample();
                param.createCriteria().andDataTypeEqualTo(PermissionTypeEnum.REAL_TABLE.getType())
                        .andRoleIdEqualTo(roleId)
                        .andDataIdEqualTo(Long.valueOf(tableId))
                        .andQueryEqualTo(YesOrNoEnum.YES.getValue());
                List<SysRoleDataPermission> list = sysRoleDataPermissionMapper.selectByExample(param);
                if (CollectionUtils.isNotEmpty(list)) {
                    tp = new RealTablePermission(table, list.get(0));
                } else {
                    tp.defaultValue(roleId, tableId, PermissionTypeEnum.REAL_TABLE.getType());
                }
            }
            tp.setEnName(table.getTableName());
            SysRoleDataPermissionExample fieldParam = new SysRoleDataPermissionExample();
            fieldParam.createCriteria().andDataTypeEqualTo(PermissionTypeEnum.REAL_TABLE_FILED.getType())
                    .andRoleIdEqualTo(roleId)
                    .andQueryEqualTo(YesOrNoEnum.YES.getValue());
            List<SysRoleDataPermission> authFields = sysRoleDataPermissionMapper.selectByExample(fieldParam);
            List<Integer> authFieldIds=new ArrayList<>();
            if(CollectionUtil.isNotEmpty(authFields)){
                authFieldIds=authFields.stream().map(i->i.getDataId()).collect(Collectors.toList());
            }
            if (CollectionUtils.isNotEmpty(fields)) {
                //查询自己的创建的字段信息
                Integer finalUserId = userId;
                List<Integer> fieldIds=authFieldIds;
                List<BdpRealTableField> fieldList = fields.stream()
                        .filter(s -> finalUserId.equals(s.getCreateUser().intValue())||fieldIds.contains(s.getId())).filter(distinctByKey(i->i.getId())).collect(Collectors.toList());
                if (CollectionUtils.isNotEmpty(fieldList)) {
                    ArrayList<RealTableFieldInfoPermission> fieldPerList = com.google.common.collect.Lists.newArrayList();
                    for (BdpRealTableField tableFieldInfo : fieldList) {
                        RealTableFieldInfoPermission field = new RealTableFieldInfoPermission();
                        field.yesValue(roleId, tableFieldInfo.getId(), PermissionTypeEnum.REAL_TABLE_FILED.getType());
                        field.setEnName(tableFieldInfo.getFieldName());
                        field.setChName(tableFieldInfo.getFieldName());
                        fieldPerList.add(field);
                    }
                    tp.setTableFieldInfos(fieldPerList);
                    dataList.add(tp);
                    savePermission(dataList);
                }
            }
        }

        //初始化表的创建者和当前租户的租户管理员的权限
        Set<String> intiCreateTable = Sets.newHashSet();
        intiCreateTable.add(table.getDbName() + "|" + table.getTableName()
                + "|" + table.getId() + "|" + table.getCreateUser());
        //当前租户的租户管理员
        Integer tenantId = ShiroUtils.getTenantId();
        List<SysTenantUser> users = sysTenantUserService.list(new LambdaQueryWrapper<SysTenantUser>().eq(SysTenantUser::getTenantId, tenantId).eq(SysTenantUser::getTenantType, 0));
        if (CollectionUtil.isNotEmpty(users)) {
            for (SysTenantUser user : users) {
                intiCreateTable.add(table.getDbName() + "|" + table.getTableName()
                        + "|" + table.getId() + "|" + user.getUserId());
            }
        }
        rangerDataService.intiCreateTable(intiCreateTable);
        List<DataApplication> applyList = dataApplicationMapper.selectListByTableId(tableId, 2);
        if (CollectionUtil.isNotEmpty(applyList)) {
            for (DataApplication dataApplication : applyList) {
                rangerDataService.saveOrUpdateRangerPolicy(dataApplication);
            }
        }
    }

    public static <T> Predicate<T> distinctByKey(Function<? super T, Object> keyExtractor) {
        Map<Object, Boolean> seen = new ConcurrentHashMap<>();
        return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
    }

}
